\documentclass[chapter,kosection, 10.5pt, romanfixed, a4paper]{oblivoir}
\usepackage{fapapersize}
\usefapapersize{210mm,297mm,14mm,*,14mm,14mm}
\usepackage[usenames,dvipsnames]{color}
\usepackage[pdftex]{graphicx}
\usepackage{fancybox}

\SelectHfonts{utgr,utbm,utpg}{utyt,utgt,utgt}
\SetHangulspace{1.5}{1.2}
\addtolength{\droptitle}{-8ex}

\newenvironment{smallquote}
{\begin{quote}\small} {\end{quote}}

\begin{document}

\title{프로그래밍 온라인 게임}
\author{darkface}
\maketitle

\begin{quote}
\flushright \footnotesize
컴퓨터 프로그래밍은 시나 음악의 창작과 같은 예술의 형식이다. \\
- 도날드 크누스
\end{quote}
\qquad

\tableofcontents

\oblivoirchapterstyle{openright}
\chapter{긴 여정의 시작}

이제 프로그래머로서 온라인 게임을 만드는 긴 과정으로 들어가 봅니다. 그 간의 경험이 일천하여 
정리될 내용이 있을까 싶기도 하지만 스스로 공부하는 삼아 추가적인 테스트와 코드를 겸하여 
진행하고자 합니다. 

이 책을 쓰면서 전에 작성한 네트워크 엔진을 시뮬레이션을 구현한 서버 엔진으로 발전시키고 
테스트를 겸해서 클라이언트 엔진을 하나 만들려고 합니다. 여러 종류의 게임을 잘 만들고 싶고 
전체 구조가 안정적이어서 프로그래머는 고생하지 않고 기획자는 만족하고 그래픽은 펑펑 내용을 
쏟아 내고 사용자는 행복한 기술 기반을 만들려고 하는 게 제 남은 인생 동안 가려고 하는 길입니다. 
\\
\\
\textcolor{RoyalBlue}{자 이제 긴 여행을 시작해 봅시다.}

\section{게임 구조의 이해}

게임은 컴퓨터에서 창조된 세계를 표현합니다. 텍스트, 이미지, 사운드 등이 최종적인 
표현의 산출물입니다. 따라서, 게임을 만들 때는 창조된 세계와 표현 두 가지를 구현해야 합니다. 

창조된 세계는 가상 현실과 비슷한 개념이지만 상상력 만으로 제한 받는 세계이기 때문에 
더욱 넓은 개념이고 어찌 보면 끝이 없기 때문에 게임 개발을 매력적으로 만드는 이유입니다. 

\subsection{창조된 세계}

\shadowbox{창조된 세계는 오브젝트와 오브젝트 간의 상호 작용의 집합이다}

오브젝트는 마땅히 정의할 말이 없습니다. 우리가 있다고 믿는 어떤 것인데 결국은 상호 작용을 
통해서만 존재가 드러납니다. 하지만 일정하게 반응하기 때문에 우리가 알게 되는 것들입니다. 
상호 작용이 존재 자체의 근거가 된다는 점은 양자 역학의 불확정성 원리로도 알 수 있습니다. 

\begin{smallquote}
불확정성원리(Uncertainty principle) 는 양자 역학에서 맞바꿈 관측량(commuting observables)이 아닌 두 개의 
관측가능량(observable)을 동시에 측정할 때, 둘 사이의 정확도에는 물리적 한계가 있다는 원리이다. 
불확정성 원리는 양자역학에 대한 추가적인 가정이 아니고 양자역학의 통계적 해석으로부터 얻어진 근본적인 결과이다. 
하이젠베르크의 불확정성원리는 위치-운동량에 대한 불확정성원리이며, 입자의 위치와 운동량을 동시에 정확히 
측정할 수 없다는 것을 뜻한다. 위치가 정확하게 측정될 수록 운동량의 퍼짐(또는 불확정도)는 커지게 되고 
반대로 운동량이 정확하게 측정될 수록 위치의 불확정도는 커지게 된다.
\end{smallquote}

결국 창조된 세계에서 가장 중요한 것은 상호 작용입니다. 이를 통해서만 경험할 수 있고 믿을 수 있고 
뭔가가 있다고 생각합니다. 

\subsection{표현}

상호 작용은 관측될 수 있어야 합니다. 표현되지 않으면 알 수 없기 때문입니다. 표현은 게임에서 
더 중요한 작용을 합니다. 재미있다고 생각하고 현실처럼 생각합니다. 즉, 몰입할 수 있게 해줍니다. 

표현은 아직 오감 중 시각과 청각이 주가 되고 키보드나 마우스를 사용하면서 일부 촉각을 사용합니다. 
청각 표현은 이미 어느 정도 원하는 만큼 표현 가능한 수준에 도달했습니다. 하지만 아직 시각적인 표현은 
무궁무진하게 남아 있습니다. 물론 청각도 언제 어떻게 표현하냐에 따라 정말 새로운 느낌의 세계를 
만들 수 있습니다. 소리만으로 진행되는 게임도 가능하겠지요. 옛날 라디오 드라마 처럼요. 

\subsubsection{사실감}

\subsubsection{일관성}

\subsubsection{몰입}


\subsection{상호작용}

이제 게임은 어떤 상호작용이 가능한가와 이를 어떻게 표현하는가가 가장 중요한 기술과 기획적인 요소가 된다는
사실을 알았습니다. 영화처럼 그림만 보여주는 이야기 방식과 게임을 근본적으로 다르게 만든다는 점에서 
상호작용이 가장 중요합니다. 

\shadowbox{게임은 상호작용과 표현의 구조이다}

게임 기획자들은 저처럼 생각하지는 않을 겁니다. 그런 기획자는 혼나야 하겠지요. 하지만 프로그래머라면
이렇게 근본이 되는 구조를 파악하고 이해해야 합니다. 


\chapter{3D 엔진의 구현과 사용}

2D 엔진으로는 게임을 성공시킬 수 없는가하면 절대로 그렇지는 않다. 던전앤파이터나 메이플 스토리는
여전히 장수하고 있는 게임이며 바둑, 포커 등의 보드 게임도 아주 큰 시장을 형성하고 있다. 

하지만 이런 2D 게임들도 3D를 사용하여 구현하고 있으며 이미지의 사용량이 적어 개발이 보다 쉽고 
표현에 제약이 적다는 점에서 3D가 대세라고 봐야 한다. 

3D 엔진은 렌더링, 애니메이션, 이펙트, 물리 처리, 사운드 플레이를 포괄하는 광범위한 영역을 
포괄한다. 모든 기능을 다 내부 스튜디오에서 개발하기는 어렵기 때문에 미들웨어를 포괄적으로 
활용하면서 표현과 시뮬레이션의 품질과 유연성에 집중하여 게임 개발을 하는 것이 좋다. 

여기서는 테스트 용도로 작성 중인 3D 엔진의 개발과 그간의 엔진 사용 경험을 중심으로 정리해 나간다. 

\section{상용 엔진의 기능}

현존하는 최고의 엔진은 Unreal 3이다. 물론 타 엔진들이 빠르게 따라오고 있긴 하나 기능의 
안정성, 다양성, 편의성에서 아직 차이는 있다. 

언리얼 엔진의 기능은 다음과 같이 나누어진다. (http://www.unrealtechnology.com 참조)
\begin{itemize}
\item 렌더링 
\item 애니메이션
\item 오디오 
\item 물리 
\item 게임 스크립팅
\item 확장 애니메이션 (Matinee)
\item 파티클 이펙트
\item 에디터 
\item 네트워킹
\end{itemize}

위와 같은 방대한 기능을 갖고 있으며 경쟁력 있는 게임을 만들기 위한 기반이 확실하게 갖추어져 있다. 
플러그인 형태로 제공되는 스피드트리, 스케일폼, 하복 등도 그 기능이 강력하여 언리얼 기반의 
사업 체계가 이미 강력하게 형성되어 있다. 

그렇다고 좌절할 필요는 없다. 에픽 게임즈가 오래된 회사이고 언리얼 엔진도 1998년 출시된 이후 
오랜 시간 동안 안정되기는 했지만 쉐이더 기반의 렌더링 기술이 보편화되고 있고 언리얼 엔진이 
특허를 많이 출허한 엔진이 아니라는 측면에서는 접근 가능하다. 단지, 오랜 시간의 인내와 
노력이 필요하다. 

\subsection{렌더링}

렌더링이 멀티 코어를 지원하는 쓰레드 기반 렌더링을 지원한다. 쓰레드를 잘 활용할 수 있는 
기능이 앞으로도 계속 중요하다. 쓰레드를 잘 활용하려면 락 처리를 줄여서 서로 분리된 
기능들의 동시성을 최고로 올리는 게 관건이다. 

컬링도 BSP나 포털 기반에서 하드웨어를 사용한 동적인 컬링으로 옮겨가고 있다. 
잘만 활용한다면 충분한 성능을 거의 대부분의 장면에 적용 가능하다. 여러 가지로 이유로 
옥트리와 k-d 트리와 같은 장면 분할 기법은 여전히 필요하다. 특히, 온라인 게임의 서버를
위해서는 반드시 필요하다. 따라서, 이런 장면 관리 기법을 적용할 수 있도록 개발해야 한다. 

렌더링은 매시, 라이팅, 텍스쳐 등을 픽셀로 변환하는 과정을 말한다. 렌더링 품질은 결국 라이팅 처리에
의해 좌우되며 기본 성능을 제공하면서 처리하는 게 필요하다. 

그래픽 하드웨어의 발전에 따라 GPU의 성능을 최대한 활용할 수 있는 방법이 필요하며 
게임의 특성에 따라 균형을 맞출 수 있는 방법이 있어야 한다. 

최근의 경향에 따른 렌더링 기능은 다음과 같다. 
\begin{itemize}
\item Occlusion 컬링
\item 상세한 캐릭터 라이팅 (노멀 맵, 여러 개의 라이팅 사용)
\item 상세한 그림자 처리 
\item Global illumination (PRT 기법의 확장)
\item Ambient occlusion (자기 차폐 그림자 처리)
\item 후 처리 효과들 (블러링, Depth of Field, Bloom 등)
\item 지형의 상세한 처리 (displacement map, lighting, LOD 등)
\end{itemize}

\subsection{애니메이션}

애니메이션은 어느 정도 안정된 기능으로 리서치도 멈추는 것으로 보인다. 
골격과 키프레임 기반의 애니가 모두 보편화되었으며 골격과 키프레임 모두에 대해 
LOD를 지원하는 게 필요하다. 특히 MMOG를 개발할 때는 더욱 중요하다. 

언리얼의 기능을 중심으로 보면 다음과 같은 기능이 필요하다. 
\begin{itemize}
\item 기본 골격, 키 프레임 애니와 LOD 지원
\item 블렌딩 
\item 노드별 애니 변경 (블렌딩 변경과 키 프레임 등의 변경)
\item 속성과 머티리얼 애니의 연결 (쉐이더 변경, 텍스처 변경, 텍스처 좌표 변경 등)
\item 애니메이션 피드백 (특정 프레임에 이벤트 연결)
\end{itemize}

\subsection{오디오}

오디오는 이미 fmod, OpenAL 등의 좋은 라이브러리들이 있다. 따라서, 이런 좋은
라이브러를 통합하여 게임에 활용 가능하게 하면 된다. 

\begin{itemize}
\item 3D 사운드, 돌비 사운드
\item 이벤트 연동 플레이 시스템 
\item 사운드 압축 기능 
\end{itemize}

\subsection{물리}

이전에 하복이 최고였다면 이제는 GPU를 활용하는  Nvidia의 PhysX가 대세이다. 
따라서, 잘 연동하는 게 중요하며 시뮬레이션과 표현에서 적절하게 분리하여 
적용할 수 있는 기법들이 더 필요하다. 

\subsection{이펙트}

파티클 기반의 이펙트와 애니메이션 기반의 이펙트가 있다. 파티클은 LOD를 
지원하는 게 필요하다. 애니메이션 기반의 이펙트를 강화하는 게 더 중요하며 
아도비의 에프터 이펙트 기능을 어느 정도 수용 가능한가가 더 중요하다. 

따라서, 에프터 이펙트에서 바로 게임에 익스포트 가능한 형태의 툴을 만들고 
파티클을 적절하게 섞어서 쓴다면 훌륭한 이펙트들을 만들 수 있다. 

\subsection{환경}

어디에도 나와 있지는 않지만 스피드 트리와 같이 대규모 자연 환경이나 
도시 환경과 같은 환경 자체를 빠르게 렌더링할 수 있는 기능이 필요하다. 
이 쪽은 특수하게 최적화 할 수 있는 기법들이 있기 때문이다. 


\section{테스트 엔진의 개발}

우리의 궁극적인 목적이 재미있는 새로운 게임의 제작에 있다면 결국 중요한 건 
몰입감 있는 재미있는 상호작용의 창조에 있다. 

물론 공개 엔진들이 많이 있긴 하지만 최고로 단순한 엔진을 하나 개발하여 다양한
시뮬레이션 모델을 테스트 해 보는 걸 목표로 했다. 렌더링, 애니메이션, 이펙트, 
파티클을 갖추고 PhysX와 OpenAL을 활용하여 물리와 사운드를 처리할 계획이다. 

\subsection{렌더링}

 
\chapter{서버 프레임워크}

\section{기반 구조}

MMOG (Massive Multiplayer Online Games)에서 요구하는 서버의 기반 구조가 
달성해야 할 목표는 다음과 같이 나누어 볼 수 있다. 

\begin{itemize}
\item 안정성 (Stability)
\item 성능 (Performance)
\item 확장성 (Scalability)
\item 빠른 동기화 (Synchronization)
\item 쉽고 빠른 개발
\end{itemize}

위 네 가지 목표를 달성하기 위한 기술은 시간에 따라 변화 발전하지만 현재까지 
리서치한 결과로는 다음과 같이 나누어 볼 수 있다. 

\begin{itemize}
\item 처리 구조 (Processing Model)
\item 통신 구조 (Communication Model)
\item 분산 구조 (Distribution Model)
\item 월드 구조 (World Model)
\item 시뮬레이션 구조 (Simulation Model)
\item 영속성 처리 구조 (Persistency Model)
\end{itemize}

각 영역별 과제와 해결 방향을 살펴보고 장단점을 비교 분석한다. 

\subsection{처리 구조}

서버의 처리 구조는 CPU 코어를 포함하여 16개 미만이 현재 일반적인 상황이다. 
다중 쓰레드를 사용하는 구조가 보편화되어 있으며 다중 쓰레드를 어떻게 
사용하는가에 따라 두 가지 정도로 나누어 생각할 수 있다. 

\subsubsection{대칭 구조}

대칭 구조란 여러 쓰레드가 월드의 부분을 동시에 실행하는 구조이다. 이런 접근 
방식은 항상 critical section에 대한 락을 걸어야 하며 락 충돌이 발생하면 
쓰레드 스위칭이 일어난다. 

대칭 구조는 다음과 같은 장점을 갖는다. 
\begin{itemize} 
\item 동시성을 최대한 올릴 수 있다
\item 데이터 복제나 이벤트 전파를 줄일 수 있다. 
\end{itemize}

하지만 다음과 같은 심각한 단점도 갖고 있다. 
\begin{itemize}
\item 락 처리가 까다로워진다. 
\item 코드 량이 늘어날수록, 시간이 지날수록 점점 느려진다.
\end{itemize}

대칭 구조의 장점을 유지하면서 락 처리를 프로그래머가 직접하지 않아도 
되는 구조에 대한 연구가 진행되고 있으며 DarkStar의 Java 서버 구현에서는
오브젝트에 대한 락을 미리 잡는 방식으로 피하고 있다. 하지만 엄청 느리다는
결정적인 단점이 있다. 

대칭 구조를 사용하여 여전히 개발하고 있으나 장기적으로 갖고 갈 방향은 아니라고 본다. 

\subsubsection{비대칭 구조}

비대칭 구조란 개별 쓰레드에서 처리하는 데이터, 월드를 분할하여 처리하는 
방식이다. 비대칭 구조는 메세지 패싱을 기본 아이디어로 삼고 있으며 이를 
계산 모델로 확립한 Actor 모델이 있다. Actor 모델은 분산 인공지능에 
적용된 Multi Agent System (MAS)의 기반 아이디어로 사용하고 있다. 

비대칭 구조로 MMOG를 만드는 것은 가능하며 다크에이지오브카멜롯, 메틴, 
썬 등에 사용되었고 넥슨의 둠바스도 이런 아이디어에 기초하고 있다. 

비대칭 구조의 장점은 다음과 같다. 
\begin{itemize}
\item 락 처리가 거의 필요 없다. (메세지 큐 정도에만 사용)
\item 시간이 지나도 성능이 떨어지지 않는다
\item 좀 더 세밀하게 분할하는 확장을 쉽게 할 수 있다
\end{itemize}

당연히 다음과 같은 단점도 있다. 
\begin{itemize}
\item 분할된 지역 기능에 대한 동시성을 올리기 어렵다
\item 각 분할 영역 간의 메세지, 데이터 전파가 필요하다
\end{itemize}

\subsubsection{처리 구조 정리}

DirectX11의 멀티 쓰레딩 구조나 기존의 쓰레드 기반 렌더러를 보면 command queue 방식을 
사용하고 있다. 렌더링 쓰레드, 물리 처리 쓰레드, 애플리케이션 쓰레드로 분할 하고 
각 쓰레드 간에 명령어를 주고 받아서 처리하는 방식이다. 

서버도 전체 월드를 지역별로 분할하고 각 지역을 좀 더 세분화 가능하게 만들고 
AI를 돌리는 쓰레드를 별도로 두는 방식으로 대칭 구조에 필적하는 성능을 
갖게 만들 수 있다. 

지금까지 경험으로 보면 이런 지역 분할 방식과 연계된 서버들은 모두 상당히 
안정적이며 유지보수도 쉽다. 

메세지 패싱을 사용하면 처리하는 쓰레드가 다른 장비에 있더라도 그대로 
적용 가능하기 때문에 가용한 CPU 수량을 늘리는 걸 거의 공짜로 할 수 있다. 

이런 장점을 활용하면 클라이언트 중의 하나가 특정 기능을 담당하도록 하는 
분산 기능도 쉽게 구현할 수 있다. 


\subsection{통신 구조}

통신은 이미 해결된 문제로 보인다. 지금까지 해결된 내용이 무엇인지만 
간결하게 살펴본다. 

\begin{itemize}
\item 대규모 통신 처리 지원 (IOCP, EPOLL, AIO 등)
\item TCP와 UDP 상의 통신 구조 
\item 패킷 암호화, 패킷 검증 (순서, 누락 등)
\item P2P 통신 처리 (홀 펀칭, Reliable UDP 등)
\end{itemize}

물론 게임을 만들다 보면 패치 시스템과 같은 전혀 다른 통신 구조를 
만들어야 하는 경우도 생긴다. 리소스 스트리밍은 게임 구현과는 
직접 연관이 없지만 서비스 품질을 올리는 데는 아주 중요하며 
서버 프로그래머가 클라이언트 프로그래머와 함께 해결해야 하는 과제이다. 

\subsection{분산 구조}

처리 구조와 어느 정도 연관되지만 서버의 장비들을 확장하거나 PC를 게임 
시뮬레이션에 직접적으로 활용하거나 (트래픽 전파나 물리 처리에 활용) 하는 
다른 차원의 분산 구조가 필요하다. 

일관성과 유일성을 보장해야 하는 길드 처리나 DB 처리는 한 곳에서 관리하는 게 
필요하다. 이런 기능들을 몰아두고 인증 정보 등을 관리하기 위한 구조로 대략
다음과 같은 서버 분산 구조를 채택한다. 

\begin{itemize}
\item 로비 서버를 두는 경우
\item 센터(백엔드) 서버를 두는 경우 
\item 역할별 서버를 두는 경우
\end{itemize}

로비를 앞 단에 두는 경우는 로비를 통해서만 게임 서버와 통신 하는 경우와 
로비가 단순 북 키핑 작업만 하는 경우가 있다. 통신을 중계하는 건 보안성이 
약간 더 올라가지만 통신 자체가 느려진다는 점에서 바람직해 보이지는 않는다. 
다크 에이지 오브 카멜롯의 경우 통신까지 중계하는 방식을 사용했다. 

센터를 두는 경우가 일반적인데 B\&B, 넥슨의 어둠시리즈까지의 게임들이 
이런 구조를 택했고 아주 많은 게임에서 주로 채택하고 있는 방식이기도 하다. 

역할별 서버를 두는 경우는 AI 서버나 로그인 서버, 커뮤니티 서버 등 큰 역할을
별도로 분리된 서버에 두는 방식의 일반적인 확장이다. 길드 컨텐츠나 여러 서버에
분산될 수 있는 파티의 경우 별도 커뮤니티 서버에서 북 키핑을 담당하는 걸 생각해 
볼 수 있으며 장점도 명확하다. AI 서버의 경우는 논란의 여지가 있다. 

\subsection{월드 구조}

MMORPG의 경우 클라이언트가 옥트리나 k-d 트리 또는 변형된 BSP 트리를 사용하여 
장면 그래프를 구성하기 때문에 클라이언트의 경우는 이들 구조를 반영하여 사용하면 된다. 

서버의 경우 시뮬레이션에서 물리적인 정확도가 점점 강조되면서 (논 타겟팅에서 특히 심함) 
충돌 처리를 통한 이동까지도 고려해야 하는 시대가 되었다. 따라서, 전체적인 구성을 
Octree나 쿼드 트리로 하고 여기에 네비게이션 매시와 지형의 속성 정보에 따른 길찾기가 
가능한 구조를 심은 후에 느슨한 충돌 처리 (박스 형태나 성긴 충돌 매시 등)를 하는 월드 
구조가 필요하다. 

처리 구조와 맞물려서 구성해야 하며 대칭형일 경우에는 락 충돌을 줄이는 구조가 필요하고
비대칭형 일 경우에는 인접 지역으로 빠르게 전파하며 전체 처리를 인원 수나 바쁜 정도에 
따라 쓰레드 배분이 가능한 구조가 필요하다. 

인스턴트 던전도 일반화되고 있기 때문에 여러 인던을 동시에 부드럽게 처리할 수 있는 구조도 
함께 고려하여 월드 데이터 구조를 초기부터 잡아야 한다. 

\subsection{시뮬레이션 구조}

전체적인 시뮬레이션 구조의 상위 구조는 Entity (또는 Actor ), 메세지 (또는 이벤트), 상태기계로
추상화 할 수 있다. 또한 데이터 클래스를 View (또는 Data)와 같은 이름으로 분리하여 처리와 
데이터를 확실하게 구분하면 패킷 처리나 클라이언트와 공유하는 부분에서 많은 이득을 볼 수 있다. 

각 처리 단위에서 메세지에 대한 subscription/dispatch 기능을 두고 타이머 기능까지 메세지로 
처리하면 서버 단위 기능 테스트를 메세지로 자동화 시킬 수 있다. 또한 연결을 찾아야만 하는 
구조를 사용하지 않으면 대규모 스트레스도 실제 서버의 데이터를 갖고 처리 가능하다. 

시뮬레이션에 대한 상세 구조는 시뮬레이션 절에서 좀 더 자세하게 살펴본다. 게임 기능이 
결국 통신과 처리 구조 상에서 시뮬레이션 기능으로 구현되기 때문에 가장 중요하고 AI와 
물리 처리와 더불어 서버의 가장한 중요한 영역이다. 

시뮬에이션이 시간 순으로 처리되어야 한다는 점에서 이벤트 정렬이 필요하다. 대칭형 쓰레드 모델을
사용하는 서버를 구현해 본 사람들은 알겠지만 채널/로비 형태의 단순한 서버 구조에서도 이벤트 순서로 
인한 버그가 자주 발생할 수 있다. 

\subsection{영속성 처리 구조}

Persistence를 처리하기 위해 DBMS를 사용한다. 아주 오래 전에는 파일을 사용한 경우도 있었지만
SQL DB의 성능 향상으로 대부분의 게임들이 관계형 DB를 사용하고 있다. 

관계형 DB의 TPS가 실시간 업데이트를 처리할 정도로 빠르지는 않기 때문에 (물론 가능은 하다)
대부분 DB 처리를 위한 서버를 하나 두어 트랜잭션을 조절하는 형태로 사용하고 있다. 

DB 서버에 캐싱 기능을 두면 성능은 많이 빨라지기는 하나 운영을 위한 툴 작업에 어려움을 
겪게 된다. 따라서, 이를 염두에 두고 캐시 서버를 작업해야 한다. 

몇 가지 캐싱 가능한 영역은 플레이어 추가 정보 (비밀 번호 제외), 인벤토리, 스킬 정보 등이 
있으며 이 쪽 테이블에 변경이 발생할 경우 게임에 접속 중인 사용자의 정보를 다시 로딩할 수 있는
방법이 필요하다 (운영 툴용 클라이언트).


\section{시뮬레이션}

서버 시뮬레이션은 두 가지 영역으로 나누어진다. 물리적인 시뮬레이션과 논리적인 시뮬레이션. 
물리적인 시뮬레이션은 MMORPG에서 점점 더 강조되는 영역이며 논리적인 시뮬레이션은 밸런스를
포함하여 전통적으로 MMORPG가 돈을 벌 수 있도록 한 영역이다. 두 가지 다 중요하고 새로운 모델을
찾아 나가는 것이 필요하다. 

\subsection{물리 기반의 월드}

물리 기반의 월드는 모든 MMORPG의 기반이 되는 이동의 핵심이다. 미사일이나 화살과 같이 
궤적이 있는 물체의 이동에도 물리적인 시뮬레이션을 사용하는 게 보편화되고 있기 때문에 
물리 충돌도 점점 중요하게 된다. 

\subsubsection{이동}

지형의 구조에 따라 다르긴 하지만 높이 기반의 일반적인 지형이라면 지형 속성 비트맵을
많이 사용한다. 속성에 따라 갈 수 없는 곳 등의 속성 표시가 가능. 해상도가 낮아지기 때문에
NPC의 경우에는 네비게이션 매시나 웨이 포인트 기능을 추가해야 한다. 

\subsubsection{탄도, 충돌}

서버에서는 클라이언트처럼 충돌을 상세하게 처리하기 어렵다. 따라서, 클라이언트를 서버 
시뮬레이션에 참여하도록 하여 상세한 충돌이나 이동을 처리하도록 하는 게 궁극적으로 
가야 할 구조로 보인다. 이렇게 할 경우 해킹 등에 대한 대처가 필요하나 서버에서 
느슨한 검증을 하고 참여 클라이언트를 파악하기 어렵도록 하며 일부의 시뮬레이션만
담당하도록 하여 조절할 수 있다. 

충돌 매시나 충돌 박스, 충돌 구를 서버에서 월드 구조로 갖고 있어야 한다. 이 구조는 
레벨 에디터에서 만들어져야 하고 네비게이션 매시, 웨이포인트, AI 특성 편집과 함께 
이루어지도록 해야 한다. 

\subsubsection{동기화}

물리 세계의 동기화는 상세하게 하려면 비용이 많이 든다. 동기화의 기본적인 알고리즘은
이벤트 동기화와 상태 동기화 두 가지가 있다. 대부분의 게임 서버에서는 이벤트 동기화를
사용하며 다옥 등 일부 게임에서는 이동의 상태 동기화를 하기도 한다. 

상태 동기화는 상세한 동기화가 가능하나 패킷량이 증가하기 때문에 이벤트 동기화와 
적절하게 균형을 잡아 가는 게 필요하다. 

\subsection{논리 기반의 월드}

서버의 대부분의 컨텐츠는 논리 기반의 시뮬에이션이다. 왜냐하면 물리세계의 동기화나 
시뮬레이션 계산량이 아직은 장비들에서 게임이 재미있을만큼 수용하기 어렵기 때문이다.

결국 아이템 판매나 캐릭터 판매와 같은 MMORPG의 핵심 유료화 모델이 동작하려면 
표현의 상세한 처리와 함께 밸런스 위주의 다양한 컨텐츠로서 동작하는 논리 기반의 
월드가 잘 구성되어야 한다. 

\chapter{온라인 게임 Construction}

\section{프로그래밍 일반}

\subsection{진행}

설계, 구현, 테스트의 일반적인 흐름이 실제로는 잘 동작하지 않는다. 물론 이 과정이 있어야 하지만
길고 큰 시스템 단위로는 동작하지 않는다. Extreme programming이 제안하는 바는 작은 단위로 
위 과정을 반복하라는 것이다. 변경도 좀 더 빠르게 반영될 수 있도록 하고 사용자에게 제공되는 
가치 중심으로 작업한다는 뜻이며 단위 테스트와 리팩터링이 가장 강력한 수단이 된다. 

\subsection{읽히는 코드}

도날드 누쓰의 literate programming은 문서와 코드를 함께 작성하는 구조이다. 게임 프로그래밍을 
이렇게 할 수는 없고 미리 주석으로 골격을 만든 후 작성 후에 정리하는 방식으로 진행할 수는 있다. 

읽히는 코드 작성에서 가장 중요한 점은 동작하는 코드에서 관심을 쉽게 이해할 수 있는 코드로 
옮겨야 한다는 점이다. 이렇게 했을 때 여러 가지 버그도 쉽게 줄일 수 있고 유지보수도 가능하며 
설계가 좀 더 나은 구조를 만들어내기가 보다 수월하다. 

읽히는 코드는 유닛 테스트와도 밀접한 관계가 있다. 사용 방식이 미리 정해진 코드는 구현에만 
신경 쓴 코드보다 훨씬 이해하기가 쉽다. 유닛 테스트는 이런 사용자와 사용 코드의 관계를 형성하여 
설계를 보다 개선하고 코딩도 간결하게 하는 데 큰 역할을 한다. 

\subsection{게으름}

너무 빨리 너무 부지런히 코딩하는 건 좋지 않다. 그리고 많은 양의 코드로 원하는 목표를 달성하는 것보다는
데이터로 내용을 채우고 코드 구조는 간결하게 가져가는 게 좋다. 유지보수 과정이 아니라면 땜빵 보다는
보다 확실한 솔루션이나 알고리즘을 정리한 후에 코딩을 시작하는 게 좋다. 

\subsection{기본}

코딩 컨벤션이 있어야 한다. 설계와 관련된 컨벤션까지는 아니더라도 명명 규칙, 헤더의 구조, 
주석 구조, 블럭 구조, 자잘한 세부 사항에 대한 가이드 등이 필요하다. 

\subsection{반드시 읽어야 할 세 가지 분야}

디자인 패턴, 리팩터링, 유닛 테스트. 

\subsection{자잘하지만 중요한 것들}

서버 프로그래머로서 요구되는 것들은 아주 많다. 이 부분은 대부분 know-how 이거나, 하지 말아야 할 것들, 
꼭 해야 할 것들 등이 있을 수 있다. 각 회사마다 이런 내용을 구체적인 기술과 함께 
오랜 시간 잘 정리해 나가는 게 필요하다. 
 
\section{게임 서버 프레임워크}

아래 세 가지로 충분하다고 할 수는 없지만 다른 문제들은 이미 많이 해결되었기 때문에 
핵심으로 생각하는 내용만 정리한다. 

\subsection{Entity, Message, 계층 구조}

Communicating sequential process에서 시작된 액터 모델은 병렬 처리 프로그래밍에 많은 영향을 미쳤고 
Multiagent System의 초석이 되었다. 

많은 게임에서 이미 Entity, Message 구조를 사용하고 있으며 HFSM이나 HCSM 또는 행동 트리와 같은 
계층 구조를 사용하고 있다. HCSM과 행동 트리는 서로 보완하면서 사용할 수 있다. 

전체 프레임워크를 Entity, Message, HCSM으로 구성하고 세부 조절을 행동 트리로 진행하는 방식이 프레임워크에는
더 적당한 것으로 보인다. 행동 트리는 상세한 AI (몬스터 AI) 등 특수한 Entity에 적용하는 게 더 나아 보이지만 
행동 트리에 대해서는 좀 더 이해가 필요하다. 

\subsection{월드와 처리 구조의 바인딩}

월드를 돌릴 구조가 필요하다. 한 안으로 월드 전체를 Octree로 구성하고 적당한 크기의 Octree에 대해 
처리 쓰레드를 붙여서 (Cell이라고 부르자) 인접한 셀과 동기화를 처리하는 식으로 구성하면 충분하다. 

인던과 같은 구조는 인던을 돌리는 셀들을 만들어서 쓰레드 대신 몇 개의 셀을 한 쓰레드에서 돌리는 방식으로
구성 가능하다. 물론 CPU가 더 필요하다면 게임에 맞게 구성할 수 있다. 

\subsection{아주 많은 옵션과 변화하는 기능 처리}

요즘은 어지간한 게임은 모두 캐릭터랑 스킬 수십개를 넘어 수백개에 근접한다. 캐릭터 종류도 많아지고
또 아이템도 다양하게 많다. 아이템에 붙는 옵션도 많고 공방이나 갬블 등을 통해 옵션을 붙이거나 
슬롯에 또 다른 아이템을 붙이거나 하는 식으로 아주 복잡한 속성을 다양하게 갖는다. 

이런 기능이 고정되어 있다면 프로그래머 입장에서는 다행이겠지만 서비스를 시작하거나 그 이전부터 
계속 추가/삭제/변경이 이루어진다. 이런 변경은 한 부분에 머물지 않고 게임 전체에 번진다. 이런 복잡함과 
변화에 대응하기 위한 구조와 처리 방법이 지속적인 컨텐츠 추가와 개발의 안정성으로 돌아온다. 성공하고 
있을 때 더욱 중요해진다. 

\subsubsection{일단 하는 게 더 중요하다}

기획에서 원하고 사용자들이 원하는 세밀한 조율, 변경, 다양한 기능은 반드시 해야 한다. 코드가 다소 지저분해지고
구현이 복잡해 지면서 프로그래머로서는 하고 싶지 않은 일이라고 하더라도 꼭 해야 한다. 이 점을 명심하는 게 
시작이다. 

\subsubsection{반드시 해야 한다면 잘 해야 한다}

이런 변화에 대응하기 위한 방법이 개별 컨텐츠별로 좀 차이가 있다. 이런 변경을 아이템, 스킬 등 세부 항목을 
살펴볼 때 더 정리해 나가도록 한다.  


\section{온라인 게임의 컨텐츠 구성}

처리 구조와 월드 구조가 만들어지고 이동과 전투가 어느 정도 되면 이제는 보다 논리적인 구조가 더 중요하게 된다. 
게임 플레이 측면의 발전도 중요하지만 함께 어울리고 성장하고 모험하는 터로서의 게임이 더 중요해진다. 


\subsection{변경 관리}

앞에서 제기한 문제인데 온라인 게임은 데이터 필드의 추가, 삭제, 변경이 발생한다. 문제는 한국에서는 더 이상
사용하지 않는 기능이 태국에서는 아직 업데이트 되지 않은 경우 등의 문제가 발생할 수 있다. 이런 문제를 해결하는 게 
서비스 개발의 안정성을 위해 중요하다.

북미에서 개발된 게임들, 주로 자세히 살펴본 다옥의 경우는 익스팬션 단위로만 업데이트를 실시한다. 그 중간에 
나오는 기능은 대부분 버그 수정 패치이다. 국산 게임에서 지향해야 할 방향도 이 쪽이 아닌가 싶다. 

변경 관리 측면에서 게임에서 사용하는 논리적인 데이터의 관리와 그래픽 리소스와 일치 문제가 중요하다. 이런 데이터 
관리를 위한 기본 원칙들은 다음과 같다. 
\begin{itemize}
\item 히스토리 가능한 형식이어야 한다. (Lua나 Json, XML 등)
\item 다른 리소스 의존 관계를 검증할 수 있거나 추출할 수 있어야 한다
\item 툴 제작이 쉽도록 자체 스키마, 검증 코드를 포함해야 한다. 
\end{itemize}

위와 같은 게임 구성 파일 형식을 갖추고 있으면 형상 관리 툴에 넣고 branch, tag 기능을 활용하여 처리 가능하다. 
그래픽 리소스는 릴리스 할 때 추출해 오는 형식으로 처리 가능하다. 월드 구성은 텍스트 형식으로 처리하기 어렵기 
때문에 별도 포맷이 있어야 한다. 

그래픽 리소스는 용량이 크고 다루기 어렵기 때문에 에이리언 브레인과 같은 전용 툴을 사용하는 걸 고려해야 한다. 

변경관리는 흥미롭고 도전적인 주제이다. 데이터와 코드의 일치, 게임 구성 데이터와 리소스의 일치, 서비스 지역별 
차이의 관리 등 아직 누구도 완전하게 도달하지 못한 어떤 경지가 있는 곳이다. 

별도의 장으로 구성하여 살펴보도록 하자. 

\subsection{스탯}

캐릭터나 플레이어의 속성 값으로 존재한다. 별도 데이터 클래스로 만들어서 조인해도 되고 
캐릭터나 플레이어의 속성 필드로 있어도 된다. 스킬, 전투, 퀘스트, 커뮤니티 등 여러 기능의 
구현 코드에서 참조할 수 있다. 

변화된다는 측면에서 보면 별도 데이터 클래스로 분리하고 논리적인 작업을 해당 클래스에 
두는 것도 바람직해 보인다. 대부분의 서버 구현에서는 캐릭터에 변수와 함수들을 둔다. 

\subsection{아이템}

온라인 게임의 경쟁이 치열해지면서 아이템의 종류가 무척이나 다양해지고 속성도 많이 추가되고 있다. 
또한 게임의 개발 단계부터 속성의 추가, 변경, 삭제 등이 빈번하게 이루어진다. 이런 점을 손쉽게 반영하도록 
하기 위해 필드 값을 아이템 종류에 따라 분리해서 사용하는 방식을 쓰고 있다. 

가장 중요한 개념은 아이템의 클래스와 인스턴스가 분리되도록 하는 것이다. 인스턴스가 분리되면 
보유한 아이템 개별적으로 수명이 관리될 수 있고 속성이 변경될 수 있기 때문에 다양한 기능의 구현이 
가능하다.  

상점에서 거래와 맞물리기 때문에 아이템의 기반이 되는 변경이 적은 부분을 상위 클래스로 만들고 서로 다른
아이템 클래스를 분리하는 것이 필요하다.

\subsection{인벤토리}

보유한 아이템만을 관리하도록 하는 게 좋다. 장착된 아이템은 캐릭터 클래스나 별도 클래스에서 관리해야 
코드가 좀 더 깔끔해진다. 가방이나 여러 슬롯을 차지하는 아이템 등 게임마다 다른 제약 조건을 반영하여 
작업해야 하며 대부분 리스트 구조로 처리 가능하다. 보다 빠르게 검색이 가능하려면 슬롯 구조와 아이템 보유 구조를
분리하여 구현할 수 있다. 

\subsection{스킬}

스킬은 데이터 측면에서는 단순하다. 스탯, 아이템이나 다른 속성 (길드 스킬 등)에 의존하는 지 여부 등이 
명시되어 있으면 되고 이들 스킬은 각 캐릭터에 보유 목록으로 존재한다.  

어려운 점은 전투에서 결과 처리이다. 대상의 상태에 따라 결과가 달라지며 확률적으로 동작하기 때문이다. 
이런 구조를 쉽게 확장하고 다양한 조건을 간결하게 서술할 수 있는 구조가 필요하다. 기획자들의 상상력은
프로그래머의 구현 능력을 뛰어넘는 경우가 허다하게 많으며 게임에 적합하며 앞선 구조를 찾아야 한다. 

\subsection{퀘스트}

트리 구조가 가장 좋다. 행동 트리와 유사한 구조의 퀘스트 트리 구조를 만들고 개별 플레이어마다 인스턴스를 
갖도록 하여 퀘스트의 시작, 진행, 분기, 종료를 관리하도록 한다. 

퀘스트는 여러 이벤트에서 점검해야 하고 퀘스트 종류가 다양할수록 검색도 잦아지기 때문에 빠르게 점검할 수 
있는 구조가 필요하다. 퀘스트 진행은 재미있고 다양하게 하고 플레이어별로 한번에 수행하는 퀘스트 수량은
적게 가져가서 서버 성능을 너무 잡아먹지 않도록 해야 한다. 

\subsection{커뮤니티}

커뮤니티 관련 DB를 분리하는 경우가 있다. 이는 커뮤니티에 들어가고 나가는 과정이 트랜잭션 처리가 필요하기 때문이다. 
DB를 분리하지 않더라도 이런 작업은 하나의 집중화된 서버에서 하는 게 필요하다. 분산하더라도 개별 오브젝트 (파티, 길드 등)는
한 서버에서만 처리하는 게 필요하다. 이렇게 해야 단순하고 간결하게 처리할 수 있다. 

\subsection{전투}

인공지능 측면이 아닌 논리적인 결과 처리에 관련된 전투 구현이 필요하다. 전투의 기본적인 기능은
전투의 진행과 데미지 계산이다. 

TBD. 


\section{인공 지능}

\subsection{이동과 A*}

게임 서버에서 인공 지능의 기본은 길 찾기이다. 몬스터가 움직이고 캐릭터를 추적하고 
도망하고 포위하고 몰려 다니고 하는 모든 요소의 기반이 길 찾기이다. 

길찾기는 그래프 탐색 알고리즘을 활용하고 AI의 모든 것은 사실 검색이기 때문에
가장 기초적인 AI 스킬이 된다. 

서버에서 길 찾기는 보다 정확하고 빠르면 사실적이어야 하는데 현재는 네비게이션 매시로 
답이 정리되었다고 본다. Path Engine이나 Nav Power 또는 Havok AI에 들어 있는 기능이며 
C9 등에서 이미 사용하였다. 

레벨 에디터에서 편집 가능해야 하며 웨이 포인트와 함께 섞어서 사용하면 좀 더 사실적이고
흥미로운 몬스터 이동 패턴을 만들 수 있다. 

\subsection{전투}

전투는 몬스터의 행동과 AI 엔티티의 편집으로 귀결된다. 행동 트리는 Task 기반 트리로 생각하는데
이들 Task는 Condition과 Action으로 이루어진다. 이런 행동 트리의 조건과 동작의 그래프 구조를
게임에서 제공된 요소로 이어 붙여서 몬스터나 몬스터 콘트롤러의 편집이 이루어지면 다양한 요소를
재미있게 만들 수 있다. 

이렇게 만들어진 요소들을 구체적인 몬스터에 적용하는 과정을 통해 실제 레벨 에디터에서 
시뮬레이션 해 볼 수 있으면 게임의 완성도를 더욱 높일 수 있다. 조건에 확률 요소를 적극 
활용할 수 있다면 질리지 않는 게임을 만들 수 있다. 

\subsection{확률 요소}

\subsubsection{확률 분포}
확률은 주사위 이후로 게임의 아주 중요한 요소이다. 아이템 드랍률이나 스킬 성공률 등도 모두 
확률에 의존하여 재미를 더 한다. 이런 확률 요소는 지금까지 일정한 확률을 사용하는 방식
\footnote{Uniform Distribution - 확률이 상수 값으로 분포한다. 예, 90\% 등}이 사용되었으나 
확률 분포를 명확하게 인식하고 관리하는 게 필요하다. 

확률 분포의 기본은 정규분포이다. 정규 분포는 평균과 표준편차로 나타낼 수 있고 이 두 가지로 
모든 확률 요소를 결정할 수 있다. 다른 분포가 더 유용하다면 그러한 분포를 사용할 수도 있다. 

\subsubsection{AI에 활용}

상태기계나 행동 트리와 같은 요소에 확률을 추가하면 좀 더 재미있는 게임 요소를 만들 수 있다. 
Fuzzy FSM과 같은 확률 요소를 갖는 상태 기계는 룰 기반의 상태 전이와 함께 다양한 재미를 추가할 수 있다. 

\subsection{레벨 에디터}

게임 플레이에 관련된 모든 데이터의 편집이 레벨 에디터로 통합되어야 한다. 레벨 에디터는 게임의 
재미를 완성하는 요소로 게임 클라이언트로서도 동작해야 한다. 서버도 레벨 에디터 안에서 실행 가능하거나
접속 가능해야 하고 서버에 있는 엔티티들이 레벨 에디터에서 사용 가능해야 한다. 

퀘스트 자체도 트리 구조로 만들고 행동 트리의 아이디어를 통합하면 보다 강력해지기 때문에 레벨 에디터에
통합 가능하다.

게임을 완성하고 서비스 개발에서 가장 강력한 기능을 발휘할 수 있는 레벨 에디터는 처음부터 공을 많이 
들여야 하고 게임의 개발과 맞물려 지속적으로 유지보수 되어야 한다. MMORPG에서는 가장 강력하며 가장 
중요한 툴이다. 


\section{테스트 프레임워크}

프로그래밍은 테스팅이다. 전문적으로 프로그래밍을 시작하면 금방 깨닫게 된다. 
설계가 중요하나 경험이 필요하고 구현된 코드는 바로 동작하기 어렵다. 설계도 
안정되려면 테스트가 필요하고 여러 번 변경을 거처야 한다. 

단위 테스트와 기능 테스트는 프로그래머가 갖는 훌륭한 두 가지 무기이다. 단위 테스트 뿐만 
아니라 기능 테스트도 자동화 시킨다면 정말 훌륭한 프로그래머로 성장할 수 있다. 

\subsection{단위 테스트}

단위 테스틑 cppunit 부터 gtest까지 여러 가지 툴이 나와 있다. 

지금까지 사용해 본 바로는 gtest가 간결하고 작성하기도 쉽다. 아래는 gtest를 
사용하여 간략한 테스트를 작성한 예이다. 정말 간단하다.

\begin{verbatim}
TEST( TestWinApp, testOne ) {
	WindowApplication app;

	int started = GetTickCount();

	app.Setup( _T("Test App"), 0, 0, 1024, 768 );
	app.Run( 500 );

	ASSERT_TRUE( GetTickCount() - started >= 500 );
}
\end{verbatim}

\subsection{기능 테스트}

기능 테스트는 개발 과정에서도 중요하다. 클라이언트가 없이 테스트 가능한 방법들이 있어야 하기 때문이다. 
컨텐츠에 따라 다르긴 하지만 HCSM 또는 HSM을 갖는 상태 기계와 월드를 이해하는 클라이언트가 필요하다. 

N.F.T \footnote{Non-intrusive Functional Test 비관입적인 기능 테스트}로 정리한 바 있으며 대략적인 아이디어와 
구성은 부록에서 볼 수 있다. 

\subsection{스트레스 테스트}

스트레스 테스트는 서버의 전체적인 성능과 확장성을 테스트 하기 위해 사용하며 
서버 개발에서는 필수적이나 초기에만 개발하여 확인하고 나중에는 유지보수하지 
않는 경향이 있다. 

스트레스 테스트는 MMORPG의 경우 대규모의 사용자 이동과 전투가 가능한 정도까지 
개발해야 하고 유지해야 한다. 특히, 서버가 대칭형 다중 쓰레드 기반일 경우에는
타이밍에 따른 데드락 발생, 이벤트 순서에 따른 처리 오류 등이 발생할 수 있기 
때문에 더 중요하다. 

\subsection{밸런스 테스트}

캐릭터가 특정한 셋업을 갖고 특정 몬스터와 싸우면 얼마나 시간이 걸리고 얼마나 보상을 
받는가를 측정하는 게 기본이다. 이런 변형된 셋업과 테스트를 빠르게 진행할 수 있도록 
해주는 도구들을 미리 개발해 놓는다면 온라인 게임의 생명인 밸런스를 유지하고 개선하고 
지켜 나가는 데 큰 도움이 될 것이다. 


\section{운영 기능}

\subsection{로깅}

서버는 표현을 클라이언트를 통해 대신한다. 서버의 유일한 표현 수단은 로깅이다. 
따라서, 강력하고 빠르며 다양한 로깅이 가능해야 제대로 된 뭔가 말 할 수 있는
서버라고 할 수 있다. 

네트워크로 접속하여 로그를 볼 수 있는 기능과 로그 중 일부를 빠르게 추출할 수 
있도록 하는 기능 등이 필요하다. 

\subsection{서버 설치와 자동 패치}

서버 설치는 전통적으로 파일 복사와 구성 파일 설정으로 이루어졌다. 

DB 설치는 스크립트를 실행하면 되도록 한다. stored procedure와 테이블들은
버전 관리에 포함해야 한다. 

자동 패치는 클라이언트에서만 이루어졌는데 MMORPG와 같이 다양하고 복잡한 데이터를
사용하는 경우에는 서버도 패치 시스템을 통해 자동 패치 되는 게 좋다. 그래야 관리 부담이 줄어들게 된다. 

이렇게 할 수 있다는 뜻은 서버 관련 파일만 패치 하는 기능이 패치 시스템에 있다는 의미이다. 

\subsection{이벤트 로깅과 리포트}

게임에서 일어나는 중요한 일들을 DB에 남기고 다시 통계로 만들고 분석하여 
게임 서비스에 반영하는 과정은 점점 더 중요해 지는 듯 하다. 

\subsubsection{아이템 트래킹}

DB 서버와 같은 곳에서 일괄하여 경제 시스템에 영향을 미치는 모든 작업에 대한 
로깅을 남기도록 한다. DB에 직접 저장될 수도 있고 상황에 따라서는 파일에 남기고 
DB에 올리는 방식으로 처리할 수도 있다. 

\subsubsection{플레이 패턴}

로그인과 로그아웃, 지역 이동, 몬스터 사냥, 파티 맺기 등에 대해 로깅을 
남기면 사용자 플레이 패턴을 찾아낼 수 있다. 될 수 있으면 광범위하게 
유의미한 데이터를 통계와 레포트를 포함하여 운영 담당 부서와 협력하에
작업하는 게 필요하다. 

\subsection{GM 기능}

GM 명령어를 사용하여 게임 클라이언트에서 직접 서버에 요청하여 
게임 상태를 변경하거나 사용자를 지원하는 게 보편화된 듯 하다. 

그 간에는 게임 GUI나 게임 콘솔만 활용하였으나 윈도우 GUI를 
생성하여 부가 기능을 구현하며 보다 쉽게 지원할 수 있도록 하는 것도 
고려해볼만한 방향이다. 

대부분의 MMORPG는 수백개에서 수천개에 달하는 명령어가 있기 때문에 
계층적으로 접근해 들어가는 명령어 구조와 도움말 기능이 필요하다. 


\section{릴리스 관리}

\subsection{자동화된 빌드와 릴리스}

개발 중인 코드와 데이터를 오늘 커밋하면 새벽에 어딘가에서 빌드되고 내부 QA 시스템에
올라가 있다. 릴리스 노트에는 커밋 메세지 중심으로 변경된 내용이 기록되어 있다. 

다음 날 아침에는 어떤 내용들이 커밋되었는 지 쉽게 찾을 수 있고 개발 일정도 실제
커밋 기준으로 측정 가능하다. 

릴리스는 자동 빌드 이후에 진행되어야 하는데 데이터 기준으로 필요한 리소스들을 가져오고 
서버 설치용 스크립트를 뽑고 설치 매뉴얼을 추가하고 해서 디렉토리별로 묶어 줘야 한다. 

여러 나라를 서비스할 경우에는 국가별 릴리스도 함께 돌아가야 한다. 
이렇게 매일마다 모든 국가에 대해 릴리스를 하는 건 테스트를 원활하게 하고 
국가별 서비스 품질을 올리는 데 중요한 기여를 할 것이다. 

\subsection{테스트}

단위 테스트와 기능 테스트가 잘 이루어지고 데이터가 병합 가능하며 검증 가능하다면 
전체적인 품질은 확 올라간다. 그래도 테스트가 필요하며 사람이 테스트를 위해 작성된 
코드보다 예외 상황을 훨씬 잘 찾는다. 

기본 테스트를 전부 자동화시킨 기능 테스트를 돌리고 그 다음에 테스트를 진행하면 
QA 효율도 상당히 높아질 것이다. 


\chapter{변경 관리}

신규 게임을 만들 때 기술적인 도전 만큼이나 흥미로운 주제이며 어떤 식으로든 해결해야 하는 주제이다. 

온라인 게임을 형상물로 보면 코드 (exe 파일), DB 테이블과 내용들, 게임 데이터들 (테이블들, 스크립트들, 기타 구성파일들), 
리소스 (모델, 텍스쳐, 애니메이션, 사운드 등)로 구성된다. 

변경 관리를 위해 활용할 수 있는 가장 강력한 도구는 서브 버전, 퍼포스와 같은 형상 관리 도구이다. 형상 관리 
도구는 이력 관리 중심으로 이루어진다. 어떤 내용이 사간의 흐름에 따라 추가, 변경, 삭제 되었는 지를 파일 단위 또는
그룹 단위로 파악 가능하다. 

이제 이 기반을 갖고 개별 요소의 파악을 시작해 본다. 

\section{데이터와 리소스}

게임에서 데이터와 리소스를 구별할 필요가 있다. 데이터는 게임의 논리적은 구성을 정의하는 자료들이고 
리소스는 표현에만 사용되는 또는 주로 표현에만 사용되는 자료들이다. 

게임 스크립트, 구성 파일, 데이터 테이블은 데이터로 볼 수 있고 텍스쳐, 모델, 애니메이션, 사운드 등은
리소스로 본다. 월드를 구성하는 정보는 두 가지를 다 포함할 수 있는데 그렇다고 하더라도 최종 산출물은
데이터와 리소스로 구분 가능해야 한다. 

이상적인 구조는 다음과 같다. 
\begin{itemize}
\item 데이터는 텍스트 형식을 갖고 병합 가능하다. 
\item 리소스는 바이너리지만 형상 관리 도구에서 관리 가능하다. 
\end{itemize}

위 두 가지를 달성하기가 만만치 않다. 그래도 가장 중요한 건 게임 데이터를 구성하는 파일들이다. 

\subsection{병합 가능한 텍스트 형식}

특정 게임에서 아이템 목록의 기반 정보를 관리하는 테이블 itembases.lua 파일이 있다고 하자. 
Lua의 테이블 형식을 사용하여 나열했고 툴도 lua로 하나 만들어서 추가, 삭제, 변경한다고 하자. 
툴에서만 해당 파일을 저장하고 저장할 때는 항상 아이템 아이디 순으로 저장한다고 가정하자. 

이렇게 가정하면 두 사람의 작업에 충돌이 없을 경우는 항상 병합 가능하다. 

좀 더 확장하면 병합 가능할 뿐만 아니라 의미를 테이블 형식, 컬럼 형식에 부여하여 쉽게 
툴을 만들 수 있는 포맷을 정의할 수 있다. Lua가 스크립트 언어이기 때문에 이 기능을 제공하기가 
더 수월하다. 

정리하면, Lua와 같은 스크립트 언어로 스스로 검증 가능하고 의미를 부여하여 툴 제작을 쉽게 하고 
최종 포맷이 정렬된 형태로 저장되는 텍스트 형식을 게임 구성파일로 사용하라!!

\subsection{충돌 해결 또는 충돌 피하기}

브랜치에서 개발하고 데이터 작업을 하고 다시 트렁크로 병합할 때 다른 브랜치나 트렁크와 
충돌이 발생할 수 있ㄴ다. 이 때 개별 데이터 파일 단위로 충돌을 해결하면서 병합해 주는 도구가 필요하다. 

개별 필드의 의존성 (다른 파일의 특정 데이터 의존)을 고려하여 충돌 해결이 가능해야 한다. 
테이블 형식의 경우 그 다지 어렵지는 않겠지만 아이디를 사용하고 정렬된 구조를 사용할 경우에는
미리 충돌을 피하기 위해 아이디를 기능 단위에 부여하는 방식이 필요하다. 아니면 브랜치 전에 
미리 확보하고 작업을 시작할 수 있다. 


\subsection{그래픽 리소스 관리}

대부분의 게임이 맥스의 원시 데이터는 차치하고 최종 게임 데이터만 수 GB를 넘어서고 있으며 점점 더 
커질 예정이다 (노멀맵, displacement map 등의 추가, 화려한 이펙트 등). 

이들 바이너리 리소스가 통합되지 않으면 변경관리가 어려워진다. 서브버전, 퍼포스, 머큐리얼 등
대부분의 형상 관리 툴을 테스트 해 보았으나 퍼포스가 유일하게 대용량 바이너리 파일들을 원활하게 
처리할 수 있었다. 

그래도 항상 꽁수는 있다. 

\subsubsection{리소스 추출 방식}

게임 구성 파일을 돌면서 필요한 리소스를 특정 파일 서버 등에서 뽑아오는 방식으로 처리할 수 있다. 
해당 파일 서버는 전체 게임 리소스를 포함하고 있으며 버전이나 디렉토리별로 나누어질 수 있다. 

파일 서버 구성은 간단한 스캔 프로그램을 설치하여 구성 가능하다. 

\subsection{언어 데이터 분리}

모든 언어 데이터를 하나의 파일에 분리하는 게 좋다. 퀘스트의 텍스트를 포함하여. 
파일이 크면 관리가 어려워지기 때문에 include 기능을 뒤서 분리 할 수 있도록 해야 한다. 

언어 데이터는 포맷 기능이 포함되어야 한다. 그래야 퀘스트에서도 사용 가능하고 여러 나라에 
그대로 주고 번역하면 자동으로 사용 가능하다. 안 그러면 나라마다 문자열 아이디가 달라지기 때문에
함께 관리하기가 곤란해지면 코드도 달라진다. 

언어 파일 형식의 한 예를 들면 다음과 같다. 
\begin{verbatim}
{ 
  193944, 
  "한 나라에 %d 사람이 살고 있었습니다.\n"
  "%s가 국왕으로 있을 시절입니다."
} 
\end{verbatim}

위와 같은 포맷을 사용하고 printf나 sprintf를 사용하면 안 된다. 그러면 죽을 수 있기 때문에. 
대신 \%d와 \%s를 해석하는 루틴을 하나 작성해야 한다. 앞에서 얘기한 대로 아이디 순으로 
동일하게 정렬하고 툴에서만 저장하면 병합 가능한 언어 데이터가 생긴다. 

\section{코드와 데이터}

이제 데이터를 변경 관리 가능하게 만드는 방법을 알았다. 이제 데이터는 코드에서 사용되므로 
코드와 일치 시키는 방법이 필요하다. 

형상 관리 툴에서 개발 라인을 관리하는 방법은 실질적으로는 두 가지 정도를 사용한다. 

\begin{itemize}
\item 개발할 때 브랜치 하고 완료 후 트렁크에 머지. 릴리스 태깅
\item 트렁크에서 개발. 릴리스 태킹
\end{itemize}

릴리스 태깅 방식은 변경이 작을 경우에 유효하고 캐주얼 게임에는 잘 맞는다. 하지만 중간에 
수 개월간 개발이 이루어지는 MMORPG의 경우에는 브랜치와 머지 방식이 더 적합해 보인다. 

머지가 가능하려면 앞에서 정리한 병합 가능한 구성 파일이 반드시 있어야 한다. 

\section{속성과 동작}

코드 내부에서 발생하는 속성과 동작의 변경이 공존해야 하는 경우 ifdef로 처리하는 게 
일반적이다. 우리의 현실은 그렇다. 북미의 경우는 그렇지 않을 수도 있겠지만... 

이 ifdef는 코드를 읽기 어렵게 만드는 문제는 그런대로 견딜 수 있으나 QA를 
어렵게 만드는 건 참기가 좀 곤란하다. 그래서 이 보다는 나은 대안들이 있어야 한다.

\subsection{속성 관리}

클래스 단위에서 멤버 필드가 추가되거나 삭제 또는 변경된 경우에 대한 경우만 다룬다. 

일부 잘못 설계된 게임 코드들에 보면 상수의 변경과 같은 게 포함된 경우도 있다. 
데이터에 포함되어야 하는 문자열, 상수, enum으로의 변환 같은 건 자동화되어야 하고 
툴 자체로 해결되어야 한다. (뭔 애기인 지 잘 모르면 고생할 준비가 되어 있는 것이다). 

필드를 굳이 변경할 이유는 거의 없고 추가된 경우는 그냥 추가된 대로 사용하면 되기 때문에
삭제된 경우만 살펴본다. 

속성이 삭제된 경우는 이 필드를 사용하는 기능이 제거된 것으로 이전의 릴리스와 완전히 단절되어야 한다. 
이와 같은 변경은 익스팬션과 같은 큰 기능이 있을 때에만 기획에서 정리해야 한다. 

만약 그렇지 않다면 또한 문제로 인지하지 않는다면 계속 뭔가 ifdef로 구분해야 하는 
어려움을 겪게 된다. 

\subsubsection{ifdef 대신 속성 사용하기}

대부분의 경우 ifdef는 변수로 처리 가능하다. 변수로 처리하면 동적으로 구성 가능하다. 따라서, 
컴파일 없이 테스트를 진행할 수 있다. 빌드된 exe의 버전 차이로 만들기 보다는 기능이 동작하는
방식을 켜고 끄는 것으로 만들어야 한다. 

\subsection{동작 관리}

동작이 다르면서 공존해야 하는 경우 함수로 분리되는 두 가지 버전을 만드는 게 가장 명확하다. 
속성 사용하기를 적용하면 코드 중간에 ifdef가 들어가는 경우를 대부분 제거할 수 있다. 

함수의 버전을 만들고 동적으로 선택하도록 하여 대부분의 ifdef를 제거 가능하다. 

\subsection{옵션화 방법}

ifdef 외에도 기능을 옵션화 시키는 다양하다. 특히, 온라인 게임의 경우는 패킷 처리를 
막아서 옵션화 할 수 있다. 또한 데이터 구성에서도 쉽게 옵션화가 가능하다. 

이 두 가지 기능을 최대한 활용하고 동작의 세세한 처리가 달라야 하는 경우에는 함수로 
분리하고 속성 필드로 켜고 꺼서 테스트 가능하게 해야 한다. 

\section{형상 관리의 예}

서브버전으로 브랜치 후 개발 흐름에 따라 개발하는 Next 게임 개발 현장을 가 본다. 

기획자가 그 동안의 아이템에는 없던 기능인 한 아이템 사용 시 여러 아이템을 주는 
기능을 추가해달라고 요청한다. 그냥 여러 아이템을 주는 것도 아니고 선택 해서 
획득할 수 있도록 해 달라는 것이다. 

\subsection{평가}

이 기능은 동작이 하나 추가된다. 이 추가된 동작은 특정한 아이템 종류 (아이템 타잎이나 분류)에 
맞물린다. 따라서, 이런 아이템이 실제로 서비스에 나가지 않으면 동작하지 않기 때문에 
그냥 기능을 추가하면 된다. 

그냥 하면 되는 데 혹시 안 된다면 뭘 잘못했는 지 확인할 필요가 있다. 

\begin{itemize}
\item 데이터나 리소스가 없을 때 리포트 하는 기능이 별도로 있는가? (동작을 멈추지 않고)
\item 병합 가능한 데이터 파일을 사용하고 있는가? (한 쪽에서 작업한 내용을 옮겨오려면)
\end{itemize}

\chapter{잔소리}

여기서는 프로그래밍, 컨텐츠 개발, 기술 개발과 관련한 그 간의 경험과 앞으로 쌓게 될 경험을
중심으로 지켜야 할 것, 해야 할 것, 하지 말아야 할 것 등을 정리해 나간다. 

Game Programming Gems 시리즈나 AI Game Programming Wisdom 시리즈 등 훌륭한 책들을 보고 
공부하는 것도 중요하지만 이런 큰 주제에서는 살피기 어려운 자잘한 경험들을 정리한다. 

\section{프로그래밍}

\subsection{컨벤션}

함께 지켜나가야 할 최소한의 규약이 필요하다. 이런 규약은 거쳐가는 프로그래머들이 많아질수록, 
코드량이 많아질수록 힘을 발휘한다. 

모든 컨벤션이 개인 단위, 조직 단위의 주관적인 경험과 취향이 반영될 수 밖에 없지만 
코드 컴플리트나 그 간의 경험에서 나온 나름대로의 기본적인 컨벤션을 정리한다. 

\subsubsection{명명규칙}

\begin{enumerate}
\item 헝가리언 노테이션을 사용하지 않는다
\item 클래스와 함수는 Camel 케이스를 사용한다
\item protected와 private함수는 소문자로 시작하여 구분한다
\item enum은 모두 대문자와 언더스코어(\_)를 사용한다
\item namespace를 사용하고 짧게 사용한다. boost처럼 길게 쓰지 않고 모듈별, 프로젝트별로 나눈다
\end{enumerate}

\subsubsection{헤더 형식}

헤더는 다른 프로그래머들이 많이 참조한다. 따라서, 보기 쉽게 선언과 구현을 구분하여 
작성하는 것이 중요하다. protected, private는 구현 사항이므로 뒤 쪽에 서술한다. 

\begin{enumerate}
\item pragma once를 사용한다. 가드 매크로는 서로 혼란을 줄 수 있다. 
\item include는 알파벳 순으로 한다. 표준 라이브러리는 마지막에 알파벳 순으로 포함한다
\item class 선언의 주석을 반드시 포함한다
\item public, protected, private 순으로 타잎, 함수, 변수 순으로 정의한다. 섹션을 많이 두지 않는다
\item 생성자, 소멸자를 제일 앞에 둔다
\item 모든 public 타잎, 함수, 변수에는 주석을 단다. 변수 주석은 변수 우측에 둔다
\item inline은 선언에 정의하지 않는다. 대신 정의에서 inline을 표시한다. 
\item inline 함수도 정의는 별도로 구분하여 서술한다
\end{enumerate}

\subsubsection{구현 형식}

\begin{enumerate}
\item 헤더에 선언된 순서대로 함수를 놓는다
\item 구현은 함수를 최대한 분리하여 작성한다 (private 함수의 활용)
\item 조건 체크를 함수 도입부에 두고 네스팅을 하지 않는 구조로 점검한다. 
\item assert를 precondition, postcondition, invariant에 대해 적극 사용한다
\item 실행 시점 에러는 철저하게 점검해야 하고 assert를 사용하지 않는다
\item 리팩터링을 테스트 코드와 함께 작성하면서 구현해야 한다
\item %{는 항상 다음 라인에 시작하도록 한다
\item 한줄 짜리 if, for, while 문을 사용하지 않는다
\item do 문은 사용하지 않는다
\item 임시 변수의 선언은 최대한 뒤로 미룬다
\item 경고는 최대한 켜고 경고를 에러로 처리한다 (모든 경고는 반드시 즉시 제거한다)
\item 사이드 이펙트를 최대한 줄이는 방향으로 구현한다
\item 이미 있는 기능을 다시 구현하지 않는다. 
\item 게으르게 구현한다. 더 쉽게 덜 귀찮게 한번에 해결할 수 있는 방향을 항상 찾는다
\end{enumerate}

\subsection{테스트}

온라인 게임에서 자동화된 테스트는 어디까지 가능할까? 아주 재미있는 주제이며 게임 구현 자체만큼
심오하다. 단위 테스트가 서버의 구석 구석 모든 코드를 뒤지며 실행 시킬 수 있는 서버라면 
그 만큼 안정적이고 유지보수가 쉽고 기능도 다양하게 들어갈 수 있다. 

단위 테스트로 해결 안 되면 자동화된 기능 테스트 (부록 참조)로 해결 가능하다. 최대한
단위 테스트로 해당 기능을 테스트 할 수 있도록 하는 것이 필요하다. 

\subsubsection{단위 테스트}

전체 서버를 실행시키고 DB까지 실행하고 DB 데이터를 초기화하고 맞춰서 단위 테스트 환경을 만들고 
가짜 클라이언트로 접속해서 해당 기능을 돌리는 것까지 실행하면 단위 테스트와 리그레션 테스트가 
가능하다. Mock-up이 아무리 크다고 할 지라도 매번 클라이언트를 실행하고 GUI를 통해 패킷을 클라이언트가 
보내줘야만 서버 기능을 테스트할 수 있다면 어찌 어찌 개발할 수는 있지만 혁신적인 게임 컨텐츠를 
지속적으로 추가하기는 아주 어려울 것이다. 따라서, 이런 단위 테스트가 가능한 구조를 만들어야 한다. 

\subsubsection{기능 테스트}

기능 테스트는 부록에서 설명하고 있고 메세지 기반의 서버라면 보다 다양한 경로를 테스트 가능하다. 
기능 테스트가 자동화되려면 리그레션이 가능해야 하는데 로그 파일 diff를 활용한 리그레션이 어느 정도 
가능하다. 반 자동화된 테스트 정도로 보면 된다. 실제 DBMS 개발 업체들은 날짜, 확률 데이터는 수작업으로 
확인하는 리그레션 기능을 갖추고 있다. 

온라인 게임은 확률 요소가 많기 때문에 실제로 어려운 영역도 많지만 확률 분포 점검과 같은 기능으로 
대체하여 어느 정도 리그레션 점검 가능한 툴의 개발이 가능해 보인다. 더 파고 들어가야 할 영역이다. 

\subsubsection{밸런스 테스트}

완전한 시뮬레이션을 통해 밸런스를 점검하는 기능은 아직 별로 시도되지 못 한 영역으로 보인다. 게임업계에서
크게 기여할 수 있는 또 다른 IT 영역의 핵심기술로 보인다. Discrete event simulation의 기법들과 결과의 
분포 함수 측정 등을 통해 가능해 보이며 밸런스 테스트가 가능하다면 기획자들은 좀 더 다양한 컨텐츠를 
안정적으로 시도해 볼 수 있을 것이다. 핵심 경쟁력을 서버 단에서 채워줄 수 있는 영역이다. 

\subsection{구조}


\section{컨텐츠 개발}

\subsection{기획 리뷰}

\subsection{클라이언트 개발}


\section{기술 개발}

\chapter{부록}

\section{N.F.T}

비관입적인 테스트 방식은 게임 코드를 사용하면서 기존 코드를 건들지 않고 기존 기능을 
테스트 하는 방식이다. 서버의 경우 메세지 기반으로 주로 동작한다면 서버에서 클라이언트로 
가는 메세지를 가로 채는 방식으로 서버 안에 NFT 기능을 구현할 수 있다. 

기존 코드를 활용하고 서버 자체에 붙어 있기 때문에 언제라도 사용할 수 있으며 
전체를 다 도는 자동화된 기능 테스트도 가능하기 때문에 아주 강력하다. 

\subsection{코드의 활용 방식}

서버 테스트 드라이버와 클라이언트 테스트 드라이버를 실제 코드에 직접 구현하는 방법이다. 
일단 양쪽의 코드를 적절히 활용하고 치트 명령어를 추가하여 필요한 상황을 셋업하는 방식을 취한다. 
기존에 GM 명령어들이 꽤 있기 때문에 보다 원할한 셋업이 가능하다. 

또한 클라이언트와 서버 코드가 병렬로 테스트되는 장점이 있다. 

\subsubsection{테스트 데이터 셋업}
테스트 셋업은 계정과 캐릭터가 전부이다. 따라서, 계정은 미리 설정하고 
캐릭터는 자유롭게 추가/삭제/변경할 수 있는 방법이 있어야 한다. 

다른 설정은 치트 명령의 추가로 해결할 수 있다. 

\subsubsection{테스트 방식}
드라이버 방식을 통합하여 사용한다. 일부 테스트 관련 패킷을 추가해야 한다. 
테스트 관련 패킷은 서버로 보내는 GM 치트 명령어들의 추가로 대부분 가능하다. 

테스트 Suite의 실행으로 테스트를 진행한다. 재활용 가능하도록 단위 테스트를 잘 나눌 필요가 있다. 

패킷 흐름에 테스트 관련 코드가 들어갈 필요가 있고 다른 도우미 기능이 필요하다. 


\subsection{NFT 설계와 구현}
NFT를 다른 온라인 게임에서 시도 했던 사례가 있는 지는 알지 못한다. 
어떻게 보면 유지보수 중이기 때문에 생각해 낸 방법일 수 있다. 
그래도 잘만 된다면 새로운 차원의 테스트 방법을 개발할 수 있다. 

\subsubsection{테스트 실행}
일반 클라이언트와 일반 서버로 실행하고 GM 명령어, 치트 명령과 같이 테스트를 시작할 수 있도록 한다. 

/test 테스트 수트 네임으로 정의된 suite를 실행한다. 

Test Suite는 미리 정의해 놓는다. 
일반 테스트와 함께 진행되며 캐릭터가 일시적으로 없을 수도 있기 때문에 명령의 결과가 표시되기 전에는 이동 등을 하면 안 된다. 


\subsubsection{테스트 셋업}
테스트가 진행되려면 테스트가 셋업 되어야 한다. 특정한 아이템이 필요할 수도 있고 
특정 레벨 이상이어야 되는 경우도 있고 특정 스킬을 보유해야 하는 등 여러 가지가 있을 수 있다. 

이런 테스트들은 최대한 클라이언트인 것처럼 속이고 치트 명령어들을 활용해서 구현하는 게 좋다. 


\section{레벨 에디터 중심의 게임 개발}

MMORPG 개발을 레벨 에디터 중심으로 개발하는 것에 관하여 정리한다. 레벨 에디터는 물리 월드와 
AI 편집과 같은 논리 월드의 핵심을 편집하는 기능을 함께 포함하고 있기 때문에 기획, 구현, 확인, 변경
사이클을 빠르게 확인 가능하다. 

네버윈터나이츠II에 사용된 ScriptEase의 패턴 기반 Behavior 편집 기능은 게임 컨텐츠를 풍부하게 만들고 
코드량을 최소화 하는 데 획기적인 아이디어를 제공한다. 좀 새로운 기능이기 때문에 
패턴 편집 기능의 실행기 설계를 먼저 정리해야 한다. 

\subsection{패턴 정의와 실행기 구조}

\subsubsection{Lua와 LuaJit}


\subsubsection{패턴 정의}


\subsubsection{패턴 실행}


\subsubsection{클래스, 템플릿, 인스턴스}



\subsection{이동, 충돌, 시야}

\subsection{엔티티 편집}

\subsection{학습}

\subsection{확률 시뮬레이션}

\subsection{협업 구조}



\end{document}